package com.huluobo.jetpackkotlindemo2006a.coroutine

import android.os.Bundle
import android.util.Log
import com.huluobo.jetpackkotlindemo2006a.databinding.ActivityCoroutineBinding
import com.huluobo.jetpackkotlindemo2006a.viewbinding.BaseActivity
import kotlinx.coroutines.*

/**
 * Created by lc on 2023/2/21.
 */
class CoroutineActivity : BaseActivity<ActivityCoroutineBinding>() {
    override fun getViewBinding(): ActivityCoroutineBinding =
        ActivityCoroutineBinding.inflate(layoutInflater)

    private val job = Job()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

//        val job = GlobalScope.launch(Dispatchers.IO) {
//            Log.i("TagA", "当前线程:" + Thread.currentThread().name)
//        }
//        val job2 = GlobalScope.launch(Dispatchers.IO) {
//            Log.i("TagA", "当前线程:" + Thread.currentThread().name)
//        }
//        //取消协程的操作
//        job.cancel()
//        job2.cancel()
//        GlobalScope.launch(Dispatchers.Main) {
//            Log.i("TagA", "当前线程:" + Thread.currentThread().name)
//        }

        //工作对象
        CoroutineScope(job).launch {
//            val result = async {
//                try {
//                    delay(3000)
//                    "运算结果:" + 3 / 0
//                } catch (e: Exception) {
//                    "结果异常"
//                }
//            }.await()
//            Log.i("TagA", result)
            val startTime = System.currentTimeMillis()
            val result = async {
                delay(2000)
                "result操作成功"
            }

            val result2 = async {
                delay(1000)
                "result2获取成功"
            }
            Log.i("TagA", "执行结果:${result.await()},${result2.await()}")
            val endTime = System.currentTimeMillis()
            Log.i("TagA", "执行时间:" + (endTime - startTime))
            //出现执行了3秒的过程,因为result执行完后,会直接执行result2,会造成线程阻塞,所以时间会产生相加
            //程序是按照上下的顺序来执行的,当我在过程中调用await时,会造成当前线程阻塞,所以是同步执行,造成结果会相加
            //如果在结果中调用await,这时是异步进行,这样时间就不会叠加
        }

        CoroutineScope(job).launch {
            loadData()
        }

        CoroutineScope(job).launch {
            //Dispatchers.IO 常用耗时操作,比如网络请求,文件读写等
            //Dispatchers.MAIN 表示程序在主线程中执行,所以在开启协程时,他的代码不一定在子线程中执行,可以进行切换
            //Dispatchers.DEFAULT 表示用于计算密集型
            //通过withContext来指定当前协程中的结果处于哪一条线程当中
            val result = withContext(Dispatchers.IO) {
                delay(2000)
                "操作成功"
            }
            Log.i("TagA", "result:$result")
        }

        loadDataFromNetWork()
    }

    //suspend 挂起的关键字,标记为当前的方法为一个挂起的方法
    //系统或者程序开发时并不知道一个方法是否会在协程中运行,所以需要添加suspend的关键字来提示其他的程序员(开发者),当前方法需要放到协程中使用
    private suspend fun loadData() {
        delay(2000) //是一个挂起方法(函数),挂起函数必须放在协程的作用域
        Log.i("TagA", "---------loadData------------")
    }

    private fun loadDataFromNetWork() {
//        Thread {//通过异步方法或者异步块来执行网络请求,使用主线程会报错(线程阻塞)
//            //执行网络请求
//            runOnUiThread {
//                //切换到UI线程展示结果
//            }
//        }
        CoroutineScope(job).launch(Dispatchers.Main) {
            val result = getResult()
            showUI(result)
        }
    }

    //使用挂起方法来处理协程中线程的嵌套
    private suspend fun getResult() = withContext(Dispatchers.IO) {
        delay(2000)
        "获取网络成功"
    }

    private fun showUI(result: String) {
        mViewBinding.tvCenter.text = result
    }
}